use std::collections::BTreeMap;
use std::fs::{self, File};
use std::io::{Error, self};

use serde_json;
use md5::{Md5, Digest};
//use sha2::{Digest, Sha256};
use tokio::{self, runtime::Runtime, sync};
use tokio::time::Instant;

type MapABData = BTreeMap<String, BTreeMap<String, String>>;

fn read_file(file_path: &str) -> Result<MapABData, Error> {
    let start = Instant::now();
    let Ok(file) = File::open(file_path).map_err(|e| {
        error!("Error: File::open({}) - {}", file_path, e);
    }) else {
        debug!("Tip : 运行耗时 read_file - {} - {:?}", file_path, start.elapsed());
        return Err(Error::other("Error: File::open failed."));
    };

    match serde_json::from_reader(file) {
        Ok(data) => {
            debug!("Tip : 运行耗时 read_file - {} - {:?}", file_path, start.elapsed());
            Ok(data)
        },
        Err(e) => {
            error!("Error: serde_json::from_reader - {} - {}", file_path, e);
            debug!("Tip : 运行耗时 read_file - {} - {:?}", file_path, start.elapsed());
            return Err(Error::other("Error: serde_json::from_reader."));
        }
    }
}

fn write_file(file_path: &str, data: &MapABData) -> Result<(), Error> {
    let start = Instant::now();
    let Ok(file) = File::create(file_path).map_err(|e| {
        error!("Error: File::create({}) - {}", file_path, e);
    }) else {
        debug!("Tip : 运行耗时 write_file - {} - {:?}", file_path, start.elapsed());
        return Err(Error::other("Error: File::create failed."));
    };

    match serde_json::to_writer_pretty(file, data) {
        Ok(_) => {
            debug!("Tip : 运行耗时 write_file - {} - {:?}", file_path, start.elapsed());
            Ok(())
        },
        Err(e) => {
            error!("Error: serde_json::to_writer - {} - {}", file_path, e);
            debug!("Tip : 运行耗时 write_file - {} - {:?}", file_path, start.elapsed());
            return Err(Error::other("Error: serde_json::to_writer."));
        }
    }
}

fn calculate_sha256(file_path: &str) -> Result<String, Error> {
    //// 读取文件内容
    //let Ok(file_content) = fs::read_to_string(file_path).map_err(|e| {
    //    error!("Error: fs::read_to_string({}) - {}", file_path, e);
    //}) else {
    //    return Err(Error::other("Error: fs::read_to_string failed."));
    //};

    //// 计算文件内容的 SHA256 值
    //let mut hasher = Sha256::new();
    //hasher.update(file_content);
    //let hash = hasher.finalize();

    let Ok(mut file) = fs::File::open(&file_path).map_err(|e| {
        error!("Error: fs::read_to_string({}) - {}", file_path, e);
    }) else {
        return Err(Error::other("Error: fs::read_to_string failed."));
    };

    //let mut hasher = Sha256::new();
    let mut hasher = Md5::new();
    let _ = io::copy(&mut file, &mut hasher)?;
    let hash = hasher.finalize();

    // 将结果转换为字符串
    Ok(format!("{:x}", hash))
}

fn calculate_sha256_all(file_path: &str) -> Result<String, Error> {
    match calculate_sha256(file_path) {
        Ok(hash) => {
            if let Ok(hash_meta) = calculate_sha256(format!("{}.meta", file_path).as_str()) {
                Ok(format!("{}|{}", hash_meta, hash))
            } else {
                Ok(hash)
            }
        },
        Err(error) => Err(error)
    }
}

fn process_map_data(root_path: &str, map_data: &mut MapABData) {
    let rt = Runtime::new().unwrap();
    rt.block_on(async {
        let count = map_data.values_mut().flat_map(|v| v.iter()).count();
        let (tx, mut rx) = sync::mpsc::channel::<(String, String, String)>(count);
        for (ab_key, ab_values) in map_data.iter_mut() {
            for ab_data in ab_values {
                let root_path_clone = String::from(root_path);
                let ab_data_clone = ab_data.0.clone();
                let ab_data_key = ab_key.clone();
                let tx_clone: sync::mpsc::Sender<(String, String, String)> = tx.clone();
                tokio::spawn(async move {
                    let result;
                    if let Ok(sha256) = calculate_sha256_all(format!("{}/{}", root_path_clone, ab_data_clone).as_str()) {
                        result = (ab_data_key, ab_data_clone, sha256)
                    } else {
                        result = (ab_data_key, ab_data_clone, String::new())
                    }
    
                    if tx_clone.send(result).await.is_err() {
                        error!("tx_clone.send");
                    }
                });
            }
        }

        drop(tx);

        trace!("map_data - {:?}", map_data);
        while let Some((ab_key, key, sha256)) = rx.recv().await {
            trace!("recv - {} - {} - {}", ab_key, key, sha256);
            if let Some(v) = map_data.get_mut(&ab_key) {
                if let Some(value) = v.get_mut(&key) {
                    value.clone_from(&sha256);
                }
            }
        }
    });
}

fn read_ab_current(root_path: &str, file_path: &str) -> Result<MapABData, Error> {
    let start = Instant::now();
    let Ok(mut map_data) = read_file(&format!("{}.current", file_path)) else {
        debug!("Tip : 运行耗时 read_ab_current {:?}", start.elapsed());
        return Err(Error::other("Error: read_file."));
    };

    //for ab_data in map_data.values_mut().flat_map(|v| v.iter_mut()) {
    //    if let Ok(sha256) = calculate_sha256(&ab_data.0) {
    //        ab_data.1.clone_from(&sha256);
    //    }
    //}

    process_map_data(root_path, &mut map_data);

    let _ = write_file(format!("{}.current", file_path).as_str(), &map_data)?;

    debug!("Tip : 运行耗时 read_ab_current {:?}", start.elapsed());
    Ok(map_data)
}

fn read_ab_last_time(file_path: &str) -> Result<MapABData, Error> {
    let start = Instant::now();
    let ret;
    if fs::metadata(file_path).is_ok() {
        ret = read_file(&format!("{}", file_path));
    } else {
        ret = Ok(MapABData::new());
    }

    debug!("Tip : 运行耗时 read_ab_last_time {:?}", start.elapsed());
    ret
}

pub fn compare_ab_diff(root_path: &str, file_path: &str) -> Result<(), Error> {
    let Ok(current) = read_ab_current(root_path, file_path) else {
        error!("Error : read_ab_current failed.");
        return Ok(());
    };

    let last = read_ab_last_time(file_path).unwrap();
    let _ = write_file(format!("{}", file_path).as_str(), &current)?;

    // 上次构建有，这次没有了，需要被删除的 ab 资源
    let last_unique: Vec<String> = last
        .keys()
        .filter(|&k| !current.contains_key(k))
        .cloned()
        .collect();

    //let mut modify: MapABData = BTreeMap::new();
    let mut modify = Vec::new();

    trace!("current : {:?}", current);
    trace!("last : {:?}", last);

    for kv in current.iter() {
        let Some(last_values) = last.get(kv.0) else {
            // 上次构建没有，这次有，需要新增的 ab 资源
            trace!("ab新增 - {}", kv.0);
            modify.push(kv.0.to_string());
            continue;
        };

        if last_values.len() != kv.1.len() {
            // ab 资源里面有增减，ab 资源需要重新构建
            trace!("ab子资源数量有增减 - {}", kv.0);
            modify.push(kv.0.to_string());
            continue;
        }

        for ab_data in kv.1.iter() {
            let Some(value) = last_values.get(ab_data.0) else {
                // 上次构建没有，这次有，ab 资源里需要新加入的包含资源
                //modify.entry(kv.0.to_string()).or_insert(BTreeMap::new()).insert(ab_data.0.clone(), ab_data.1.clone());
                //continue;

                // 上次构建没有，这次有，ab 资源需要重新构建
                trace!("ab变动 - {} - {}", kv.0, ab_data.0);
                modify.push(kv.0.to_string());
                break;
            };

            trace!("--- {} - {} - {}", ab_data.0, value, ab_data.1);

            if value != ab_data.1 {
                // 上次构建有，这次也有，并且 sha256 值变了，ab 资源需要重新构建的子资源
                //modify.entry(kv.0.to_string()).or_insert(BTreeMap::new()).insert(ab_data.0.clone(), ab_data.1.clone());

                // 上次构建有，这次也有，并且 sha256 值变了，ab 资源需要重新构建
                trace!("ab变动 - {} - {}", kv.0, ab_data.0);
                modify.push(kv.0.to_string());
                break;
            }
        }
    }

    let _ = write_result_to_file(file_path, modify, last_unique);
    Ok(())
}

fn write_result_to_file(
    file_path: &str,
    modify: Vec<String>,
    delete: Vec<String>,
) -> Result<(), Error> {
    //match write_file(
    //    format!("{}.build", file_path).as_str(),
    //    &modify,
    //) {
    let start = Instant::now();
    if modify.is_empty() {
    } else {
        match fs::write(format!("{}.build", file_path), modify.join("\n")) {
            Ok(_) => {}
            Err(e) => {
                error!("Error: fs:write({}.build) - {}", file_path, e);
                debug!("Tip : 运行耗时 write_result_to_file {:?}", start.elapsed());
                return Err(Error::other("Error: fs:write."));
            }
        }
    }

    if delete.is_empty() {
    } else {
        match fs::write(format!("{}.delete", file_path), delete.join("\n")) {
            Ok(_) => {}
            Err(e) => {
                error!("Error: fs:write({}.delete) - {}", file_path, e);
                debug!("Tip : 运行耗时 write_result_to_file {:?}", start.elapsed());
                return Err(Error::other("Error: fs:write."));
            }
        }
    }

    debug!("Tip : 运行耗时 write_result_to_file {:?}", start.elapsed());
    Ok(())
}
